/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.servicelayer.gamelogic.managerimpl;

import cz.fi.muni.diplomka.common.Coordinates;
import cz.fi.muni.diplomka.common.enumeration.TileType;
import cz.muni.fi.diplomka.datalayer.dao.CityDao;
import cz.muni.fi.diplomka.datalayer.daoimpl.CityDaoImpl;
import cz.muni.fi.diplomka.datalayer.entity.CityEntity;
import cz.muni.fi.diplomka.servicelayer.dto.City;
import cz.muni.fi.diplomka.servicelayer.dto.Player;
import cz.muni.fi.diplomka.servicelayer.dto.Tile;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.CityBuildingManager;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.CityManager;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.CityResourcesManager;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.CityUnitsManager;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.PlayerManager;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.WorldManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;

/**
 *
 * @author Jakub Kutil
 */
public class CityManagerImpl implements CityManager {

    private CityDao cityDao = new CityDaoImpl();
    private PlayerManager playerManager = new PlayerManagerImpl();
    private WorldManager worldManager = new WorldManagerImpl();
    private Mapper mapper = new DozerBeanMapper();
    private CityResourcesManager cityResourcesManager = new CityResourcesManagerImpl();
    private CityUnitsManager cityUnitsManager = new CityUnitsManagerImpl();
    private CityBuildingManager cityBuildingManager = new CityBuildingManagerImpl();

    @Override
    public void createCity(City city) {
        if (city == null) {
            throw new IllegalArgumentException("City can not be null.");
        }
        if (this.getCitiesByPlayerId(city.getPlayerId()).isEmpty()) {
            city.setCoordinates(this.getEmptyCityPlace());
        }
        cityDao.addCity(mapper.map(city, CityEntity.class));
        City newCity = this.getCityByName(city.getName());
        cityResourcesManager.createStartingResourcesForCity(newCity.getId());
        cityUnitsManager.createStartingUnitsForCity(newCity.getId());
        cityBuildingManager.createStartingBuildingsForCity(newCity.getId());

        Tile tile = new Tile();
        tile.setCoordinates(newCity.getCoordinates());
        tile.setType(TileType.city);
        worldManager.editTile(tile);

    }

    @Override
    public void editCity(City city) {
        if (city == null) {
            throw new IllegalArgumentException("City can not be null.");
        }
        cityDao.editCity(mapper.map(city, CityEntity.class));
    }

    @Override
    public Player getOwnerOfCity(Long cityId) {
        if (cityId == null) {
            throw new IllegalArgumentException("City Id can not be null.");
        }
        return playerManager.findPlayerById(cityDao.getCityById(cityId).getPlayerId());
    }

    @Override
    public List<City> getCitiesByPlayerId(Long playerId) {
        if (playerId == null) {
            throw new IllegalArgumentException("PlayerId can not be null.");
        }
        List<City> cities = new ArrayList<>();

        for (CityEntity cityEntity : cityDao.getCitiesOfPlayer(playerId)) {
            cities.add(mapper.map(cityEntity, City.class));
        }

        return cities;
    }

    @Override
    public List<City> getAllCities() {
        List<City> cities = new ArrayList<>();

        for (CityEntity cityEntity : cityDao.getAllCities()) {
            cities.add(mapper.map(cityEntity, City.class));
        }

        return cities;
    }

    @Override
    public Coordinates getEmptyCityPlace() {
        boolean ok = false;
        Coordinates coordinates = new Coordinates();
        Coordinates upperLeftCorner = worldManager.getUpperLeftCorner();
        Coordinates lowerRightCorner = worldManager.getLowerRightCorner();
        Random random = new Random();
        while (ok == false) {
            int x = random.nextInt(Math.abs(upperLeftCorner.getX_coordinate()) + lowerRightCorner.getX_coordinate());
            int y = random.nextInt(upperLeftCorner.getY_coordinate() + Math.abs(lowerRightCorner.getY_coordinate()));

            coordinates.setX_coordinate(upperLeftCorner.getX_coordinate() + x);
            coordinates.setY_coordinate(upperLeftCorner.getY_coordinate() - y);
            if (x != 0 && y != 0 && worldManager.getTileAtPosition(coordinates.getX_coordinate(), coordinates.getY_coordinate()).getType() == TileType.plain) {

                Tile tile = worldManager.getTileAtPosition(coordinates.getX_coordinate(), coordinates.getY_coordinate());
                tile.setType(TileType.city);
                worldManager.editTile(tile);
                ok = true;
            }
        }
        return coordinates;
    }

    @Override
    public City getCityByName(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name can not be null.");
        }
        return mapper.map(cityDao.getCityByName(name), City.class);
    }

    @Override
    public City getCityById(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("ID can not be null.");
        }
        return mapper.map(cityDao.getCityById(id), City.class);
    }

    @Override
    public City getCityAtPosition(Coordinates coordinates) {
        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }
        return mapper.map(cityDao.getCityAtPosition(coordinates), City.class);
    }
}
